# -*- coding: utf-8 -*-

from w.html.useful import JScript, MetaContent, CSSArea, CSSImportArea
from w.blocks.containers.block import Block as BlockContainer, IBlock
from w.blocks.block import BaseBlock as Block
from w.html.base import ITag
from w.html.doctypes.preferable import Title
from w.html.doctypes.preferable import Html, Head as HeadTag, Body as BodyTag,DTD, Div

from w.javascript.expression import toJS
from w.settings import W

class Document(object):
    def setJSPath(self,p):
       W.BLOCKS.JS_PATH_PREFIX = p
    
    def setCSSPath(self,p):
       W.BLOCKS.CSS_PATH_PREFIX = p

    jsPathPrefix = property(fget=lambda s: W.BLOCKS.JS_PATH_PREFIX, fset=setJSPath)
    cssPathPrefix = property(fget=lambda s: W.BLOCKS.CSS_PATH_PREFIX, fset=setCSSPath)
    
    def __init__(self, title=None, noJScript=False):
        self.title = title
        self.metaHeader = MetaContent('utf-8')

        self.head = HeadTag()
        self.body = BodyTag()
        self.html = Html([self.head,self.body])

        self.noJScript = noJScript
        self.jsSettings = {'historyEnabled':False,
                           'callbacks':{'onRefresh': None,
                                         },
                          }
        self.preJScript = ''
        self.postJScript = ''

        self.scriptFiles = []
        self.cssFiles = []
        self.css = ''
    
    _wjsInitCode = """preWWInit = function() {
    initSettings(%s);}"""

    def walkProcessor(self, where, process, res):
        for el in where:
            process(el, res)
            if isinstance(el, ITag):
                self.walkProcessor(el,process,res)
        return res

    def jsCode(self):
        def process(el, res):
            if hasattr(el,'jsCode') and not el.noJSInit:
                res.append(el.jsCode())
        l = self.walkProcessor(self.head, process, [])
        return self.walkProcessor(self.body, process, l)

    def cssCode(self):
        def process(el, res):
            if isinstance(el, IBlock):
                res.update([el.cssCode()])
        return self.walkProcessor(self.body, process, set(self.css))

    def cssBlock(self):
        def process(el, res):
            if isinstance(el, IBlock):
                res.update(el.cssFiles)
        return self.walkProcessor(self.body, process, set(self.cssFiles))
    
    def jsBlock(self):
        def process(el, res):
            if isinstance(el, Block):
                res.update(el.scriptFiles)
        return self.walkProcessor(self.body, process, set(self.scriptFiles))

    def makeJSInclusion(self, names):
        return [JScript(hsrc='%s/%s'%(W.BLOCKS.JS_PATH_PREFIX, jsFName)) for jsFName in names]

    def make(self):
        self.head[0:0] = [self.metaHeader]
        self.head[1:1] = [CSSImportArea(['%s/%s'%(W.BLOCKS.CSS_PATH_PREFIX, c) for c in self.cssBlock()])]
        self.head[2:2] = [CSSArea(self.cssCode())]

        if not self.noJScript:
            self.head[3:3] = [JScript(self._wjsInitCode%toJS(self.jsSettings)+'\n'+self.preJScript)]
            self.head[4:4] = self.makeJSInclusion(Block.scriptFiles+list(self.jsBlock()))

            self.head.append(JScript(self.jsCode()))
            if self.postJScript:
                self.head.append(JScript(self.postJScript))
        
        self.head.append(Title(self.title))
        return [DTD, '\n', self.html]
    
    def __str__(self):
        return ''.join([str(block) for block in self.make()])

class PartDocument(Document):
    def __init__(self, content):
        Document.__init__(self)
        if isinstance(content, list):
            self.body.extend(content)
        else:
            self.body.append(content)

    def make(self):
        if not self.noJScript:
            self.body[0:0] = [JScript(self._wjsInitCode%toJS(self.jsSettings)+'\n'+self.preJScript)]
            self.body[1:1] = self.makeJSInclusion(self.jsBlock())

            self.body[2:2] = JScript(self.jsCode())
            if self.postJScript:
                self.body[3:3] = JScript(self.postJScript)

        return [e for e in self.body]

